package com.xdy.server.core2;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.*;

/**
 * @Author: XDY.
 * @Email: 2280944114@qq.com
 * @CreateTime: 2023-03-13  17:20
 * @Description: 封装请求
 * @Version: 1.0
 */
public class Request {

    //请求空行
    private static final String CRLF = "\r\n";

    private SocketChannel socketChannel;

    //请求报文信息
    private String requestInfo;

    //请求头信息
    private String headInfo;

    //请求方法
    private String method;

    //请求url
    private String url;

    //请求uri
    private String uri;

    //请求参数
    private String queryStr;

    //存储请求参数
    private Map<String, List<String>> parameterMap;

    //存储请求头信息
    private Map<String,String> headMap;

    public Request(SocketChannel socketChannel) {
        this.socketChannel = socketChannel;
        parameterMap = new HashMap<>();
        headMap = new HashMap<>();
        try {
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int len = 0;
            while ((len = socketChannel.read(byteBuffer)) > 0){
                requestInfo = new String(byteBuffer.array(), 0, len);
            }
            System.out.println(requestInfo);
        } catch (Exception e) {
            System.err.println("请求出错啦~，错误信息："+e.getMessage());
            return;
        }
        //分解字符串
        if (requestInfo != null){
            parseRequestInfo();
        }
    }

    private void parseRequestInfo() {
        //获取请求方式
        method = requestInfo.substring(0, requestInfo.indexOf("/")).trim().toUpperCase();
        //解析请求头
        int headStartIndex = requestInfo.indexOf(CRLF) + 1;
        int headEndIndex = requestInfo.lastIndexOf(CRLF);
        headInfo = requestInfo.substring(headStartIndex,headEndIndex).trim();
        //封装请求头信息到map中
        convertHeadMap();
        //获取请求url
        int urlStartIndex = requestInfo.indexOf("/");
        int urlEndIndex = requestInfo.indexOf("HTTP/");
        url = requestInfo.substring(urlStartIndex, urlEndIndex).trim();
        int queryIndex = url.indexOf("?");
        if (queryIndex > 0) {//表示存在请求参数
            String[] urlArray = url.split("\\?");
            uri = urlArray[0];
            queryStr = urlArray[1];
        } else {
            uri = url;
            queryStr = "";
        }
        //如果是GET请求则已经获取请求参数，POST请求还需要拼接最后的请求参数
        if (method.equals("POST")) {
            if (queryStr == "") {
                queryStr = requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
            } else {
                queryStr += "&" + requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
            }
        }
        //如果存在请求参数，则封装到map中
        if (queryStr.length() > 0) {
            convertQueryMap();
        }
    }

    /**
     * 封装请求头信息
     */
    private void convertHeadMap() {
        String[] headKeyValues = headInfo.split(CRLF);
        for (String heads : headKeyValues) {
            String[] kv = heads.split(":",2);
            kv = Arrays.copyOf(kv, 2);
            String key = kv[0].trim();
            String value = kv[1].trim();
            headMap.put(key,value);
        }
    }

    /**
     * 封装请求参数为map
     * token=1245&username=xlk777&password=123456
     */
    private void convertQueryMap() {
        String[] keyValues = queryStr.split("&");
        for (String query : keyValues) {
            String[] kv = query.split("=");
            //数组长度至少为2,如果不为2，则重新生成数组长度
            kv = Arrays.copyOf(kv, 2);
            //获取key和value
            String key = kv[0];
            String value = kv[1] == null ? null : decode(kv[1], "UTF-8");
            //存储到map中
            if (!parameterMap.containsKey(key)) {
                //判断是否是第一次
                parameterMap.put(key, new ArrayList<>());
            }
            //保存值到list
            parameterMap.get(key).add(value);
        }
    }

    /**
     * 处理中文
     *
     * @param value url编码字符
     * @param enc   字符集
     * @return
     * @throws UnsupportedEncodingException
     */
    private String decode(String value, String enc) {
        try {
            return URLDecoder.decode(value, enc);
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * 过去请求参数对应的多个值
     *
     * @param key
     * @return
     */
    public String[] getParameters(String key) {
        List<String> values = parameterMap.get(key);
        if (values == null || values.size() < 1) {
            return null;
        }
        return values.toArray(new String[0]);
    }

    /**
     * 获取请求参数对应的一个值
     *
     * @param key
     * @return
     */
    public String getParameter(String key) {
        String[] values = getParameters(key);
        return values == null ? null : values[0];
    }

    /**
     * 获取head请求头信息
     * @param head
     * @return
     */
    public String getHead(String head){
        if (headMap == null || headMap.size() < 1){
            return null;
        }
        return headMap.get(head);
    }

    public String getMethod() {
        return method;
    }

    public String getUrl() {
        return url;
    }

    public String getUri() {
        try {
            return URLDecoder.decode(uri,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public String getQueryStr() {
        return queryStr;
    }
}
